package com.woniu.sharepark.leasesystem.common.service.impl;

import com.alipay.api.AlipayApiException;
import com.woniu.sharepark.common.JsonResult;
import com.woniu.sharepark.common.dao.UserInfoDAO;
import com.woniu.sharepark.common.pojo.Login;
import com.woniu.sharepark.common.pojo.UserInfo;
import com.woniu.sharepark.leasesystem.common.constant.SystemConstant;
import com.woniu.sharepark.leasesystem.common.dao.IndentFormDAO;
import com.woniu.sharepark.leasesystem.common.dao.OrderFormDAO;
import com.woniu.sharepark.leasesystem.common.pojo.IndentForm;
import com.woniu.sharepark.leasesystem.common.pojo.OrderForm;
import com.woniu.sharepark.leasesystem.common.service.OrderFormService;
import com.woniu.sharepark.leasesystem.lessor.dao.CarParkDAO;
import com.woniu.sharepark.leasesystem.lessor.pojo.CarPark;
import com.woniu.sharepark.leasesystem.tenant.dao.CarDAO;
import com.woniu.sharepark.leasesystem.tenant.pojo.Car;
import com.woniu.sharepark.platformsystem.dao.ScaleDAO;
import com.woniu.sharepark.platformsystem.dao.VoucherDAO;
import com.woniu.sharepark.platformsystem.pojo.Scale;
import com.woniu.sharepark.platformsystem.pojo.Voucher;
import com.woniu.sharepark.util.Calculate.CalculateUtil;
import com.woniu.sharepark.util.Calculate.TimeUtil;
import com.woniu.sharepark.util.GetLoginUtil;
import com.woniu.sharepark.util.MD5Encoding;
import com.woniu.sharepark.util.alipay.GoAlipay;
import com.woniu.sharepark.util.websocket.MsgWebSocketServer;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author DELL
 * @date 2019/6/4 10:13
 * version v1.0
 */

@Service
public class OrderFormServiceImpl implements OrderFormService {

    @Resource
    private OrderFormDAO orderFormDAO;

    @Resource
    private UserInfoDAO userInfoDAO;

    @Resource
    private CarParkDAO carParkDAO;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private CarDAO carDAO;

    @Resource
    private IndentFormDAO indentFormDAO;

    @Resource
    private ScaleDAO scaleDAO;

    @Resource
    private VoucherDAO voucherDAO;


    /**
    * 查询支付信息
    * @title selectOrderFormById
    * @param orderFormId
    * @return com.woniu.sharepark.pojo.OrderForm
    * @author DELL
    * @date 2019/6/3 15:20
    **/
    @Override
    public OrderForm selectOrderFormById(Integer orderFormId) {
        return orderFormDAO.selectByPrimaryKey(orderFormId);
    }


    /**
     * 生成订单编号
     * @title createOrderNumber
     * @param carPark
     * @return java.lang.Integer
     * @author DELL
     * @date 2019/6/6 10:31
     **/

    @Override
    public JsonResult createOrderNumber(CarPark carPark) {
        OrderForm orderForm = (OrderForm) redisTemplate.opsForValue().get(GetLoginUtil.getLogin().getlAccount()+"ing");
        if ( orderForm !=null){
            return JsonResult.error("您有订单正在进行，是否前往查看",orderForm);
        }
        //根据车位生成唯一订单号
        String md5 = MD5Encoding.lowerMD5(carPark.getcAddress()+carPark.getcPrice()+carPark.getUserInfo().getuName());
        CarPark redisCarPark= (CarPark) redisTemplate.opsForValue().get(md5);
        if (redisCarPark != null){
            return JsonResult.error("对不起，您手慢了");
        }

        //将订单编号存入redies 并设置过期时间
        redisTemplate.opsForValue().set(""+md5,carPark);
        redisTemplate.expire(""+md5,100L, TimeUnit.SECONDS);

       //将订单编号放入session
        Session session  = SecurityUtils.getSubject().getSession();
        Login login = (Login) session.getAttribute("currentUser");
        session.setAttribute(login.getlAccount()+"orderNumber",md5);
        session.setAttribute(login.getlAccount()+"orderCarParkId",carPark.getId());

        //多余操作
        SystemConstant.CARPARK_STATUS="付款中";
        System.out.println(carPark.getId());
        carParkDAO.updateStatus(SystemConstant.CARPARK_STATUS,carPark.getId());
        redisTemplate.opsForValue().set("carPark:"+carPark.getId(),carPark.getId());
        redisTemplate.expire("carPark:"+carPark.getId(),100L, TimeUnit.SECONDS);
        return JsonResult.ok("抢单成功");
    }


    /**
    * 租车支付
    * @title payOrder
    * @param date
    * @return java.lang.Integer
    * @author DELL
    * @date 2019/6/4 15:36
    **/

    @Override
    @Transactional
    public JsonResult payOrder(Date date,Integer voucherId){

        //取出订单编号
        Session session = SecurityUtils.getSubject().getSession();
         Login login = (Login) session.getAttribute("currentUser");
         String orderNumber = (String) session.getAttribute(login.getlAccount()+"orderNumber");
         UserInfo userInfo = userInfoDAO.selectByPrimaryKey(login.getUserInfo().getuId());

         //从redis中取出车位信息
         CarPark carPark = (CarPark) redisTemplate.opsForValue().get(orderNumber);
         //过时或错误
         if (carPark == null){
             return JsonResult.error("订单已失效");
         }

        carPark = carParkDAO.selectByPrimaryKey(carPark.getId());

        //判断账户余额是否足够
        long resultTime = TimeUtil.timeNum(date);


        double orderMoney = CalculateUtil.mul(resultTime,carPark.getcPrice());
        Voucher voucher = null;
        //判断有无使用代金卷
        if (voucherId != null){
             voucher = voucherDAO.selectByPrimaryKey(voucherId);
             orderMoney = CalculateUtil.sub(orderMoney,voucher.getvSum());
             orderMoney = CalculateUtil.kepDecimal(orderMoney);
            if (orderMoney <= 0){
                orderMoney = 0.0;
            }
        }
        //查询当前用户money信息

        if (orderMoney > userInfo.getuMoney()){
            //账户余额不足请前往充值
            return JsonResult.error("账户余额不足，是否前往充值");
        }

        //查询车辆信息当前用户
         Car car  = carDAO.selectCarById(userInfo.getuId());
         //生成订单信息
         String orderFromNumber = MD5Encoding.createOrderNumber(userInfo);
         SystemConstant.ORDER_STATUS = "已租";
         OrderForm orderForm = new OrderForm();
         orderForm.setoTime(new Date());
         orderForm.setoEndtime(date);
         orderForm.setoStatus(SystemConstant.ORDER_STATUS);
         orderForm.setoNumber(orderFromNumber);
         orderForm.setoTotalmoney(orderMoney);
         orderForm.setcId(carPark.getId());
         orderForm.setCarId(car.getCarId());
         orderForm.setVoucher(voucher);
         //插入数据库
         orderFormDAO.insertSelective(orderForm);


        //租客付款
        int rows = userInfoDAO.updateReduceMoney(userInfo.getuId(),orderForm.getoTotalmoney());


        //修改车位状态
        SystemConstant.CARPARK_STATUS = "已租";
        carParkDAO.updateStatus(SystemConstant.CARPARK_STATUS,carPark.getId());


        //抽成比例 扣款
        String success = updateMoneyAll(orderForm,carPark,orderMoney);

        //删除使用的代金卷
        if (voucherId != null){
            voucherDAO.deleteVoucherById(voucher.getvId());
        }

        //生成流水信息
        SystemConstant.IF_STATUS="已付款";
        String orderMd5 = MD5Encoding.lowerMD5(new Date().toString()+carPark.getuId()+login.getlAccount()+login.getUserInfo().getuId());
        IndentForm indentForm= new IndentForm(orderMd5,SystemConstant.IF_STATUS,"租车",orderMoney,login.getUserInfo().getuId(),carPark.getuId(),new Date());
        indentFormDAO.insertSelective(indentForm);
        System.out.println("时间"+resultTime);
        OrderForm orderForm1 = orderFormDAO.selectOrderByOnumber(orderFromNumber);
        redisTemplate.opsForValue().set(login.getlAccount()+"ing",orderForm1);
        redisTemplate.expire(login.getlAccount()+"ing",resultTime,TimeUnit.MINUTES);
        redisTemplate.delete(orderNumber);
        redisTemplate.delete("carpark:"+carPark.getId());
        session.removeAttribute(login.getlAccount()+"orderNumber");
        return JsonResult.error("租车成功",orderForm1);
    }

    @Transactional
    public String updateMoneyAll(OrderForm orderForm,CarPark carPark,Double ordereMoney) {
        Scale scale = SystemConstant.scale;
        UserInfo communityUser = userInfoDAO.selectCommunityUserinfo(carPark.getId());
        Double communityMoney = CalculateUtil.mul(scale.getsCommunity(),ordereMoney);
        userInfoDAO.updateReduceMoney(communityUser.getuId(),-communityMoney);


        //平台账户
        Double platformMoney = CalculateUtil.mul(scale.getsSystem(),ordereMoney);
        userInfoDAO.updateReduceMoney(3,-platformMoney);

        //出租账户
        Double rentMoney = CalculateUtil.mul(scale.getsRent(),ordereMoney);
        userInfoDAO.updateReduceMoney(carPark.getuId(),-rentMoney);
        UserInfo carParkUserinfo = userInfoDAO.selectByPrimaryKey(carPark.getuId());

        return "success";
    }


    /**
     *  分页查询历史订单信息
     * @param currentPage, pageSize
     * @param pageSize
     * @return
     */
    @Override
    public List<OrderForm> selectConsumptionList(Integer currentPage, Integer pageSize) {
        return orderFormDAO.selectConsumptionList(currentPage,pageSize);
    }

    /**
    *
    * @title invest
    * @param  money
    * @return java.lang.String
    * @author DELL
    * @date 2019/6/10 9:50
    **/
    @Override
    public String invest(Double money) throws AlipayApiException {
        Session session= SecurityUtils.getSubject().getSession();
        Login login = (Login) session.getAttribute("currentUser");

        String  investOrdere = MD5Encoding.lowerMD5(new Date().toString()+login.getlAccount()+money);
        String url = GoAlipay.payMoney(investOrdere,money,"充值");

        //流水信息
        SystemConstant.IF_STATUS="待付款";
        IndentForm indentForm = new IndentForm(investOrdere,SystemConstant.IF_STATUS,"充值",money,login.getUserInfo().getuId(),2,new Date());

        indentFormDAO.insertSelective(indentForm);
        return url;
    }

    @Override
    public List<OrderForm> findByCids(String cids) {
        return orderFormDAO.selectByCids(cids);
    }

    @Override
    public List<OrderForm> findOrderByCids(String cids) {
        return orderFormDAO.selectOrderByCids(cids);
    }

    @Override
    public List<OrderForm> findAllOrder() {
        return orderFormDAO.selectAllOrder();
    }

    @Override
    @Transactional
    public String alipaySuccess(HttpServletRequest request, HttpServletRequest response) throws AlipayApiException, UnsupportedEncodingException {
        System.out.println("充值中！！");
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            /*valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");*/
            params.put(name, valueStr);
        }

        //调用SDK验证签名
       /* boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);*/
         boolean signVerified = true;
        //——请在这里编写您的程序（以下代码仅作参考）——

   /* 实际验证过程建议商户务必添加以下校验：
   1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
   2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
   3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
   4、验证app_id是否为该商户本身。
   */
        //验证成功
        if(signVerified) {
            //商户订单号
            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");

            //付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");

            if(trade_status.equals("TRADE_FINISHED")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意： 尚自习的订单没有退款功能, 这个条件判断是进不来的, 所以此处不必写代码
                //退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
            }else if (trade_status.equals("TRADE_SUCCESS")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //如果有做过处理，不执行商户的业务程序

                //注意：
                //付款完成后，支付宝系统发送该交易状态通知

                // 修改订单状态，改为 支付成功，已付款; 同时新增支付流水
                /* orderService.updateOrderStatus(out_trade_no, trade_no, total_amount);*/

                /* Order order = orderService.getOrderById(out_trade_no);*/
                /* Product product = productService.getProductById(order.getProductId());*/

                System.out.println("********************** 支付成功(支付宝异步通知) **********************");
                System.out.println("订单号"+out_trade_no);


                //修改支付流水
                SystemConstant.IF_STATUS="已付款";
                indentFormDAO.updateStateByNumber(SystemConstant.IF_STATUS,out_trade_no);

                //修改用户金额
                Integer uid = indentFormDAO.selectDraweeByNumber(out_trade_no);
                Double totalMoney = Double.parseDouble(total_amount);
                userInfoDAO.updateReduceMoney(uid,-totalMoney);
            }

        }else {//验证失败
            System.out.println("支付, 验签失败...");
        }
        return null;
    }

    /**
    * 租车订单完成修改相应状态
    * @title orderSuccess
    * @param orderForm
    * @return void
    * @author DELL
    * @date 2019/6/11 19:29
    **/

    @Override
    @Transactional
    public void orderSuccess(OrderForm orderForm) {
        SystemConstant.ORDER_STATUS = "完成";
        SystemConstant.CARPARK_STATUS = "未租";
        orderFormDAO.updateStatus(orderForm.getoId(),SystemConstant.ORDER_STATUS);
        carParkDAO.updateStatus(SystemConstant.CARPARK_STATUS,orderForm.getcId());
        CarPark carPark = carParkDAO.selectByPrimaryKey(orderForm.getcId());
        /*Login login = (Login) SecurityUtils.getSubject().getSession().getAttribute("currentUser");*/

       /* redisTemplate.delete(login.getlAccount()+"ing");*/

        try {
            MsgWebSocketServer.sendToUser("车位号："+carPark.getcNumber()+"订单已完成,请前往查看","18981819999","");
        } catch (Exception e) {

        }
    }

    @Override
    public Map findOrderById(Integer id) {
        Map map = new HashMap();

        OrderForm orderForm  = null;
        try {
            orderForm = orderFormDAO.selectOrder(id);
            orderForm.getcId();
        } catch (NullPointerException e) {
            orderForm = orderFormDAO.selectByPrimaryKey(id);
        }
        System.out.println(orderForm);
        map.put("orderForm",orderForm);
        Session session = SecurityUtils.getSubject().getSession();
        Login login = (Login) session.getAttribute("currentUser");
        map.put("userInfo",login.getUserInfo());
        CarPark carPark= carParkDAO.selectByPrimaryKey(orderForm.getcId());

        map.put("carpark",carPark);
        map.put("car",carDAO.selectByPrimaryKey(orderForm.getCarId()));
        return map;
    }

    /**
    * 查找当前用户代金券已完成 or 正在进行中的订单
    * @title findAllOrderForm
    * @param uId, ordereStuats
    * @return java.util.List
    * @author DELL
    * @date 2019/6/17 15:59
    **/

    @Override
    public List findAllOrderForm(Integer uId,String ordereStuats) {
        Car car = carDAO.selectCarById(uId);
        System.out.println(car);
        List list = orderFormDAO.findAllOrderForm(car.getCarId(),ordereStuats);
        List noVoucherList= orderFormDAO.findOrderNoVoucher(car.getCarId(),ordereStuats);
        try {
            noVoucherList.get(0);
        }catch (IndexOutOfBoundsException e){
            return list;
        }

        for(Object orderForm : noVoucherList){
            list.add(orderForm);
        }

        System.out.println(list);
        return list;
    }

    @Override
    public JsonResult payIng() {
        Session session = SecurityUtils.getSubject().getSession();
        Login login = (Login) session.getAttribute("currentUser");

        String orderNumber = (String) session.getAttribute(login.getlAccount()+"orderNumber");
        System.out.println(orderNumber);
        if (orderNumber == null){
            return JsonResult.error("暂无订单");
        }
        UserInfo userInfo = login.getUserInfo();

        //从redis中取出车位信息
        CarPark carPark = (CarPark) redisTemplate.opsForValue().get(orderNumber);

        try {
            carPark = carParkDAO.selectByPrimaryKey(carPark.getId());
        } catch (NullPointerException e) {

        }
        return JsonResult.ok("success",carPark);
    }


    /**
    * 统计完成订单数量
    * @title coountSuccessOrder
    * @param uId
    * @return java.lang.Integer
    * @author DELL
    * @date 2019/6/20 15:35
    **/
    @Override
    public Integer coountSuccessOrder(Integer uId) {
        Car car = null;
        try {
            car = carDAO.selectCarById(uId);
            car.getCarId();
        } catch (Exception e) {
            return null;
        }
        return orderFormDAO.coountSuccessOrder(car.getCarId());
    }

    @Override
    public JsonResult findAllOrderToJsonResult() {
        return new JsonResult("", com.woniu.sharepark.constant.SystemConstant.SUCCESS_CODE,orderFormDAO.findAllOrder(((Login)SecurityUtils.getSubject().getSession().getAttribute("currentUser")).getUserInfo().getuId()));
    }

}
